package com.rc.saas.mini.component;

import com.rc.saas.mini.common.utils.DateHelper;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

/**
 * ID生成器
 * @author wangzhengwei
 * @create 2021/12/21
 */
@Component
public class UidGenerator {
    private static final String[] chars = new String[]{
            "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
            "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n",
            "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
            "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N",
            "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"};

    private final static String WXPAY_PREFIX = "W";
    //支付宝前缀
    private final static String ALIPAY_PREFIX = "A";
    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmsss");

    //枪号默认长度14位
    private final int GUNNO_LENGTH = 14;

    /**
     * 生成短信验证码
     *
     * @return
     */
    public String genSmsAuthCode() {
        String code = "" + (100000 + new SecureRandom().nextInt(899999));
        return code;
    }

    /**
     * 生成充值订单号
     * @param tenantPrefix
     * @param mobile
     * @return
     */
    public String genWxRechargeOutTradeNo(String tenantPrefix, String mobile) {
        if (StringUtils.isBlank(tenantPrefix) || StringUtils.isBlank(mobile)) {
            return null;
        }

        //使用数字0-9，生成20个code point(维基百科称之为'码位')的随机字符串
        //RandomStringGenerator generator = new RandomStringGenerator.Builder().withinRange('0', '9').build();
        //String randomNumbers = generator.generate(4);

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        String timeStamp = dateFormat.format(System.currentTimeMillis());

        //编码规则(30位): 支付方式(1位:W微信支付/A支付宝)+运营商简码(4位) + 用户用户后4位 + 时间戳到毫秒17位+uuid后4位
        String num = WXPAY_PREFIX + StringUtils.right(tenantPrefix.trim(), 4) + StringUtils.right(mobile.trim(), 4) + timeStamp + StringUtils.right(UUID.randomUUID().toString(), 4);
        return num;
    }

    /**
     * 生成支付宝充值订单号
     *
     * @param tenantPrefix
     * @param mobile
     * @return
     */
    public synchronized String genAliRechargeOutTradeNo(String tenantPrefix, String mobile) {
        if (StringUtils.isBlank(tenantPrefix) || StringUtils.isBlank(mobile)) {
            return null;
        }

        //使用数字0-9，生成20个code point(维基百科称之为'码位')的随机字符串
        //RandomStringGenerator generator = new RandomStringGenerator.Builder().withinRange('0', '9').build();
        //String randomNumbers = generator.generate(4);

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        String timeStamp = dateFormat.format(System.currentTimeMillis());

        //编码规则(30位): 支付方式(1位:W微信支付/A支付宝)+运营商简码(4位) + 用户用户后4位 + 时间戳到毫秒17位+uuid后4位
        String num = ALIPAY_PREFIX + StringUtils.right(tenantPrefix.trim(), 4) + StringUtils.right(mobile.trim(), 4) + timeStamp + StringUtils.right(UUID.randomUUID().toString(), 4);
        return num;
    }

    /**
     * 生成外部充电订单号
     *
     * @param tenantCode
     * @return
     */
    public synchronized String genChargeTenantCode(String tenantCode) {
        if (StringUtils.isBlank(tenantCode)) {
            return null;
        }
        //编码规则(27位):9 + 12位日期时间 + 6位随机数
        StringBuffer outOrderNum = new StringBuffer(tenantCode);
        outOrderNum.append(DateHelper.dataToString(new Date(), DateHelper.DATE_FORMAT_YYMMDDHHMMSS));
        outOrderNum.append(String.format("%06d", (int) (Math.random() * 100000)));
        return outOrderNum.toString();
    }


    /**
     * 生成瑞晨设备认证流水
     * @return
     */
    public synchronized String generateEquipAuthSeq(String tenantCode) {
        String timeStamp = sdf.format(System.currentTimeMillis());
        timeStamp = tenantCode + timeStamp;
        return timeStamp;
    }

    /**
     * 生成用户呢称
     * @return
     */
    public synchronized String genRegisteNickname() {
        //如果不是微信登录，没有呢称，所以需要设置默认呢称
        String r1 = RandomStringUtils.random(3, "abcdefghijklmnopqrstuvwxyz");
        String r2 = RandomStringUtils.random(3, "0123456789");
        return ("用户" + r1 + r2);
    }

    /**
     * 生成业务策略查询流水
     * @return
     */
    public synchronized String generateEquipBizSeq(String tenantCode) {
        String timeStamp = sdf.format(System.currentTimeMillis());
        timeStamp = tenantCode + timeStamp;
        return timeStamp;
    }


    /**
     * 生成外部充电订单号
     * @param gunNo
     * @return
     */
    public synchronized String genChargeOutOrderNum(String gunNo) {
        if (StringUtils.isBlank(gunNo)) {
            return null;
        }

        if (gunNo.length() < GUNNO_LENGTH) {//枪编号不足后面补0
            gunNo = StringUtils.rightPad(gunNo, GUNNO_LENGTH, "0");
        } else if (gunNo.length() > GUNNO_LENGTH) { //枪编号超长,截取后14位
            gunNo = StringUtils.right(gunNo, GUNNO_LENGTH);
        }

        //编码规则(30位):14位枪号 + 12位日期时间 + 4位随机数
        StringBuffer outOrderNum = new StringBuffer(gunNo);
        outOrderNum.append(DateHelper.dataToString(new Date(), DateHelper.DATE_FORMAT_YYMMDDHHMMSS));
        outOrderNum.append(String.format("%04d", (int) (Math.random() * 1000)));

        return outOrderNum.toString();
    }

    /**
     * 生成登录TOKEN
     * @return
     */
    public synchronized String genLoginToken() {
        return genShortUuid();
    }

    /**
     * 生成短UUID
     * @return
     */
    public String genShortUuid() {
        UUID uuid = UUID.randomUUID();
        long most = uuid.getMostSignificantBits();
        long least = uuid.getLeastSignificantBits();
        StringBuilder stringBuilder = new StringBuilder();
        int radix = 62;
        for (int i = 0; i < 11; i++) {
            int mi = (int) most % radix;
            int li = (int) (least % radix);

            stringBuilder.append(chars[mi < 0 ? (mi + 62) : mi]);
            stringBuilder.append(chars[li < 0 ? (li + 62) : li]);

            most = most / radix;
            least = least / radix;
        }
        return stringBuilder.toString();
    }
}
